package com.douguo.recipe.sina;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;

import android.util.Log;

public class Http extends Connector {

	private Callback callback;
	private HttpConfig config;

	private HttpURLConnection conn;
	private OutputStream outputstream;
	private InputStream in;

	private boolean cancel;

	public Http(Callback callback, HttpConfig config) {
		this.callback = callback;
		this.config = config;
	}

	public Http(Callback callback) {
		this(callback, new HttpConfig());
	}

	public synchronized void cancel() {
		cancel = true;
	}

	public void close() {
		try {
			if (outputstream != null) {
				outputstream.close();
				outputstream = null;
			}
			if (in != null) {
				in.close();
				in = null;
			}
			if (conn != null) {
				conn.disconnect();
				conn = null;
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void run() {
		try {
			// 获得接入点
			String typeName = Device.getInstance().getNetType(
					callback.getContext());
			if (typeName == null || typeName.equals("")) {
				callback.onException(new IOException(
						"No available net service!"));
				return;
			}
			// 得到连接字符
			String uri = callback.getUrl();
			if (uri == null || uri.equals("")) {
				callback.onException(new NullPointerException("Uri is null"));
				return;
			}
			// 得到Http
			HashMap<String, String> header = null;
			Param p = callback.getHeader();
			if (p != null) {
				header = p.toMap();
			}

			String host = "";
			int splitIndex = uri.indexOf("?");
			if (splitIndex == -1) {
				host = uri;
			} else {
				host = uri.substring(0, splitIndex);
			}
			URL url = null;
			conn = null;
			// 得到Http方法
			String method = config.getRequestMethod();

			if (cancel) {
				return;
			}

			// 处理CMWAP
			if (typeName.equalsIgnoreCase("cmwap")) {
				url = new URL(NetHelper.getCMWapHost(host));

				conn = (HttpURLConnection) url.openConnection();
				conn.setRequestProperty("X-Online-Host",
						NetHelper.getCMWapParam(host));

				conn.setRequestProperty("Accept", "*/*");
			} else {
				url = new URL(uri);
				conn = (HttpURLConnection) url.openConnection();
			}

			if (header != null && !header.isEmpty()) {
				Iterator<Entry<String, String>> iter = header.entrySet()
						.iterator();
				while (iter.hasNext()) {
					Entry<String, String> entry = iter.next();
					String key = (String) entry.getKey();
					String val = (String) entry.getValue();

					conn.setRequestProperty(key, val);
				}
			}
			conn.setConnectTimeout(config.getTimeOut());
			conn.setReadTimeout(config.getTimeOut());
			conn.setRequestMethod(method);
			conn.setDoOutput(true);
			conn.setUseCaches(false);

			Log.d("UMessage", "<Url: > " + url);
			if (method.equalsIgnoreCase("POST")) {
				byte[] sendData = callback.getPostParam();
				if (sendData != null) {
					outputstream = conn.getOutputStream();
					outputstream.write(sendData, 0, sendData.length);
					outputstream.flush();
					outputstream.close();
					Log.d("UMessage", "<Http Url>: "
							+ new String(callback.getPostParam()));
				}
			}

			Log.d("UMessage", "<Http Header>: " + (header == null ? "" : header.toString()));
			int responseCode = conn.getResponseCode();
			Log.d("UMessage", "<Response> : " + responseCode + "");

			if (responseCode >= 500) {
				callback.exception(new HttpException(responseCode));
				return;
			}
			if (responseCode >= 400) {
				callback.exception(new HttpException(responseCode));
				return;
			}

			if (cancel) {
				return;
			}
			in = conn.getInputStream();
			// int nDataLen = conn.getContentLength();
			// if (nDataLen <= 0) {
			// callback.exception(new IOException("Connect failed."));
			// return;
			// }

			final int BUFFER_SIZE = 1024 * 2;
			byte[] buffer = new byte[BUFFER_SIZE];

			ByteArrayOutputStream baos = new ByteArrayOutputStream();

			int readLen = in.read(buffer);
			while (readLen != -1) {
				baos.write(buffer, 0, readLen);
				readLen = in.read(buffer);
			}

			close();
			byte[] data = baos.toByteArray();
			Log.d("UMessage", "Result: " + new String(data, "utf-8"));
			callback.recieve(data);
		} catch (IOException e) {
			callback.exception(e);
		} finally {
			close();
		}
	}
}
